/*
 * bdexpr.h - Bound ED Expression
 * Clunix, cezanne@clunix.com, 2005
 * Clunix, joon626@clunix.com, 2005
 *
 * Copyright (c) 2005 by Clunix Inc. All Rights Reserved.
 */

#ifndef _EDBD_BDEXPR_H_
#define _EDBD_BDEXPR_H_

#include "edbd.h"
#include "edbd_conn.h"

#define BDEXPR_MAGIC		0x12345678
#define BDEXPR_FREED_MAGIC	0x87654321
#define LNPSENSOR_MAGIC		BDEXPR_MAGIC
#define LNPSENSOR_FREED_MAGIC	BDEXPR_FREED_MAGIC

typedef enum {
	LNPSENSOR_NONE = 0,
	LNPSENSOR_WCARD,
	LNPSENSOR_REF,
	LNPSENSOR_PLAIN,
	LNPSENSOR_EOF
} lnpsensor_type_t;

struct bdexpr_t;
struct lnpsensor;

typedef struct {
	struct lnpsensor	*lnpsensor;
	ECMBOOL		is_vector;
	sr_t		*sr;
	ecm_hashtable_t	hash_vpivots;
#ifdef ECM_DEBUG
	char		*LNP;
#endif
} topsensor_t;

typedef struct lnpsensor {
	lnpsensor_type_t	type;
	topsensor_t		*topsensor;
	struct lnpsensor	*parent;
	sr_t			*sr_pivot;
	sr_t			*sr_trail_LNP;
	struct bdexpr		*bdexpr;
	union {
		ecm_hashtable_t		subhash;
		struct lnpsensor	*subsensor;
	} child;
#ifdef ECM_DEBUG
	ecm_uint32		magic;
	char			*edexpr;
	char			*anchor;
	char			*pivot;
#endif
} lnpsensor_t;

typedef enum {
	BDI_CAST,
	BDI_FUNC,
	BDI_ASRTV,
	BDI_LNP,
	BDI_MEMBERLNP,
	BDI_SEQUENTIAL,
	BDI_VECTOR,
	BDI_VECTOR1,
	BDI_COND,
	BDI_CASE,
	BDI_CASEVAR,
	BDI_CNP,
	BDI_CNP1,
	BDI_SET,
	BDI_XECREATE,
	BDI_XEDELETE,
	BDI_SUBENTITY,
	BDI_SAME,
	BDI_NOTSAME,
	BDI_REXEC,
	BDI_NAME,
	BDI_CHILDCNT,
	BDI_ACTUATOR,
	BDI_EXIST,
	BDI_VECTORPLUS,
	BDI_VECTORMINUS,
	BDI_OWNER,
	BDI_FILE,
	BDI_LOGICALAND,
	BDI_LOGICALOR,
	BDI_BITWISEOR,
	BDI_HOMOSET,
	BDI_HOMOSETHAS,
	BDI_MEMBER,
	BDI_CALL,
	BDI_CALLONEWAY,
	BDI_ARGVAR,
	BDI_UIARG,
	BDI_UIVAR,
	BDI_CTXVALVAR,
	BDI_STAGEVAR,
	BDI_WHILE,
	BDI_CS,
	BDI_XECREATE_SA
} bdi_type_t;

typedef struct bdexpr {
#ifdef ECM_DEBUG
	ecm_uint32	magic;
#endif
	bdi_type_t	type;
	ECMBOOL		passive;
	sr_t		*sr;
	srt_t		srt;
	reactor_t	*reactor;
	ecm_mutex_t	mutex;
	ecm_uint32	refcnt;

	union {
		struct u_asrtv {
			sr_t	*sr;
		} asrtv;
		struct u_lnp {
			topsensor_t	*topsensor;
			sr_t		*sr_LNP;
		} lnp;
		struct u_memlnp {
			ecm_hashtable_t	topsensors;
			ecm_hashtable_t	entities;
			ecm_uint32	level;
			sr_t		*sr_LNP;
		} memlnp;
		struct u_func {
			ECMBOOL		autonomous;
			int		func_id;
			sr_t		*sr_bdexprs;
			struct bdexpr	*bdexpr_func;
#ifdef ECM_DEBUG
			char		*edexpr;
#endif
		} func;
		struct u_subent {
			ecm_hashtable_t	topsensors;
			ecm_hashtable_t	entities;
			sr_t		*sr_LNP;
			struct bdexpr	*bdexpr_entity;
		} subent;
		struct u_casevar {
			ecm_uint32	level;
		} casevar;
		struct u_argvar {
			ecm_uint32	idx;
			sr_t		*sr_LNP;
		} argvar;
		struct u_uivar {
			char	*name;
		} uivar;
		struct u_ctxvalvar {
			ecm_uint32	row, col;
		} ctxvalvar;
		struct u_stagevar {
			sr_t		*sr_stage;
		} stagevar;
		struct u_rexec {
			struct bdexpr	*bdexpr_node;
			sr_t	*sr_edexpr;
		} rexec;
	} u;
	struct list_head	list;
} bdexpr_t;

typedef struct {
	conn_t	*conn;
	sr_t	*sr_members;
	sr_t	*sr_casevars;
	sr_t	*sr_args;
	ecm_ptrs_t	*ptrs_delayed;
	const sr_t	*sr_anchor;
} exectx_t;

typedef enum {
	EDEXPR_REACTOR_MODE,
	EDEXPR_UIEXEC_MODE,
	EDEXPR_CNP_MODE,
} edexpr_bindmode_t;

void edbd_free_bdexpr_topsensor(bdexpr_t *bdexpr);

sr_t *get_lnpsensed_sr(edbd_conn_t edbd_conn, bdexpr_t *bdexpr);
sr_t *get_memlnpsensed_sr(edbd_conn_t edbd_conn, bdexpr_t *bdexpr, sr_t *sr);
sr_t *get_subentsensed_sr(edbd_conn_t edbd_conn, bdexpr_t *bdexpr);

edbd_bdexpr_t bind_edexpr(const sr_t *sr_anchor, const sr_t *sr_edexpr, reactor_t *reactor, ecm_uint32 nargs, srt_t *srt_args, const sr_t *sr_ctxvals, edexpr_bindmode_t bindmode, ecm_uint32 *perrlineno, char **perrmsg);
ECMBOOL get_edexpr_srt(srt_t srt_anchor, const sr_t *sr_edexpr, const sr_t *sr_ctx_val, edexpr_bindmode_t bindmode, srt_t *psrt_ret, ecm_uint32 *perrlineno, char **perrmsg);
ECMBOOL get_srt_with_stage(srt_t srt_base, const sr_t *sr_stage, const sr_t *sr_ctxvals, srt_t *psrt_ret, char **perrmsg);

ECMBOOL exec_edexpr(edbd_conn_t edbd_conn, const sr_t *sr_anchor, sr_t *sr_args, const sr_t *sr_ctxvals, const sr_t *sr_edexpr, sr_t **psr_res);
edb_err_t exec_special_edfunc(edbd_conn_t edbd_conn, const char *funcname, sr_t *sr_args, sr_t **psr_res);
sr_t *edbd_run_edexpr(exectx_t *exectx, ebc_ndid_t ndid, const sr_t *sr_edexpr);

void bdexpr_CS_lock(edbd_conn_t edbd_conn, const char *lockname, ECMBOOL logging);
void bdexpr_CS_unlock(edbd_conn_t edbd_conn, const char *lockname, ECMBOOL logging);
void edbd_CS_lock(edbd_conn_t edbd_conn, const char *lockname);
void edbd_CS_unlock(edbd_conn_t edbd_conn, const char *lockname);

sr_t *bdexpr_get(edbd_conn_t edbd_conn, const sr_t *sr_anchor, const sr_t *sr_LNP, srt_t srt_result);

srt_t bdexpr_get_srt(const sr_t *sr_anchor, const sr_t *sr_LNP);
srt_t bdexpr_get_srt_with_srt(srt_t srt, const sr_t *sr_LNP);

void bdexpr_set_result(bdexpr_t *bdexpr, sr_t *sr);

#ifdef ECM_DEBUG

char *dbg_get_lnpsensor_info(lnpsensor_t *lnpsensor);

#endif

#endif
